#ifndef BUTLER_H
#define BUTLER_H

#include <QtService>
#include <head/g_functionbase.h>
#include <element/baseudpreceiver.h>
#include <support/pie.h>
#include <support/messagehelper.h>
#include "g_ver.h"
#include "m_fhs.h"

class Butler : public QObject
{
    Q_OBJECT
public:
    explicit Butler(QObject *parent = nullptr):
        QObject(parent)
    {
        receiver=nullptr;
        hasCollector=false;
        QString host=sp_getRegValue(REG_APP,"msg_host").toString();
        if(!host.isEmpty())
        {
            hasCollector=true;
            msgHelper.setHostInfo(host,SP_UID);
        }
    }

    void receivedMessage(const QByteArray &data)
    {  
        QCborValue value=QCborValue::fromCbor(data);
        if(value.isInvalid() || !value.isMap())
        {
            if(hasCollector)
                msgHelper.warning("Message Format Error");
            else
                QtServiceBase::instance()->logMessage("Message Format Error",
                                                      QtServiceBase::Warning);
            return;
        }

        QCborMap pie=value.toMap();
        QString action=pie.value("action").toString();
        if(action.isEmpty())
        {
            if(hasCollector)
                msgHelper.warning("Action is Empty");
            else
                QtServiceBase::instance()->logMessage("Action is Empty",
                                                      QtServiceBase::Warning);
            return;
        }

        QString extra=pie.value("extra").toString();
        if(extra.isEmpty())
        {
            if(hasCollector)
                msgHelper.warning("Extra is Empty");
            else
                QtServiceBase::instance()->logMessage("Extra is Empty",
                                                      QtServiceBase::Warning);
            return;
        }

        if(action == "log")
        {
            if(hasCollector)
                msgHelper.log(extra);
            else
                QtServiceBase::instance()->logMessage("[log] " + extra,
                                                      QtServiceBase::Information);
            return;
        }
        else if(action == "cmd" || action == "open" || action == "invoke")
        {
            QProcess::startDetached(extra);
            if(hasCollector)
                msgHelper.log(QString("[%1] %2").arg(action).arg(extra));
            else
                QtServiceBase::instance()->logMessage(QString("[%1] %2")
                                                      .arg(action)
                                                      .arg(extra),
                                                      QtServiceBase::Information);
        }
        else
            if(hasCollector)
                msgHelper.warning(QString("[%1] Not Recognized").arg(extra));
            else
                QtServiceBase::instance()->logMessage(QString("[%1] Not Recognized").arg(extra),
                                                      QtServiceBase::Warning);
    }

    void start()
    {
        startReceiver();

        if(hasCollector)
            msgHelper.log(QString(SP_NAME) + " Started");
        QtServiceBase::instance()->logMessage(QString(SP_NAME) + " Started",
                                              QtServiceBase::Information);
    }

    void stop()
    {
        stopReceiver();

        if(hasCollector)
            msgHelper.log(QString(SP_NAME) + " Stopped");
        QtServiceBase::instance()->logMessage(QString(SP_NAME) + " Stopped",
                                              QtServiceBase::Information);
    }

    void startReceiver()
    {
        if(receiver == nullptr)
        {
            receiver=new BaseUdpReceiver(nullptr,PORT_COMPLEX,false);
            connect(receiver,&BaseUdpReceiver::received,this,&Butler::receivedMessage);
            connect(&recvThread,&QThread::finished,receiver,&QObject::deleteLater);
            receiver->moveToThread(&recvThread);
        }
        recvThread.start();
    }

    void stopReceiver()
    {
        recvThread.quit();
        recvThread.wait();
    }

private:
    BaseUdpReceiver *receiver;
    QThread recvThread;
    MessageHelper msgHelper;
    bool hasCollector;
};

#endif // BUTLER_H
